#include "GAF_Window.h"
#include "GAF_Application.h"
#include "GAF_Platform.h"

// 屏蔽“未引用标签”警告
#pragma WARNING(disable:4102)

#define SCENE_NULL			((Scene*)0x11111111)

namespace GAF
{
	void Window::ResetCWStruct(CreateWindow& cw)
	{
		cw.pWindow		= NULL;
		cw.nWidth		= 800;
		cw.nHeight		= 600;
		cw.isFullScreen		= false;
		cw.isScalable		= false;
		cw.isNoFrame		= false;
		cw.isCenter		= false;
		cw.strTitle		= "App";

		cw.bdlOther.Clear();
	}

	Window::Window()
	{
		ATTRIB(FullScreen)	= false;
		m_pWndHandle		= NULL;
		m_pscnMain		= SCENE_NULL;
		m_pscnTop		= SCENE_NULL;
		m_pscnShow		= SCENE_NULL;
		m_pscnCall		= SCENE_NULL;
		m_isExitWnd		= false;
		m_isShowWnd		= false;

		SYS_MEMCPY(&ATTRIB(Size), &GAF_SIZE_ZERO, sizeof(Size));

#ifdef GAF_FPS_CONTROL
		SetFPS(0);
		m_ttSaveFPST = 0;
		m_ttFPSTUse = 0;
#endif
	}

	Window::~Window()
	{
	}

	bool Window::InitWindow(CreateWindow& cw)
	{
		GAF_ASSERT(m_pWndHandle == NULL);

		m_pWndHandle = OnInitWindow(cw);

		if(m_pWndHandle == NULL)
			m_pWndHandle = GAF_pTHEPLATFORM->NewWindow(cw);

		if(m_pWndHandle == NULL)
			return false;

		ATTRIB(Size).nWidth = cw.nWidth;
		ATTRIB(Size).nHeight = cw.nHeight;
		ATTRIB(FullScreen) = cw.isFullScreen;

		return true;
	}

	bool Window::ShowWindow()
	{
		m_isShowWnd = GAF_pTHEPLATFORM->ShowWindow(m_pWndHandle);
		
		if(m_isShowWnd)
		{
			m_pscnMain = SCENE_NULL;
			m_pscnTop = SCENE_NULL;
			m_pscnShow = SCENE_NULL;
			m_pscnCall = SCENE_NULL;
		}

		return m_isShowWnd;
	}

	void Window::HideWindow()
	{
		GAF_pTHEPLATFORM->HideWindow(m_pWndHandle);
		m_isShowWnd = false;
	}

	bool Window::RunWindow()
	{
		GAF_CHECK_R(m_isShowWnd, false);

		while(m_pscnMain != NULL)
		{
			if(!OnceWindow())
				break;

			// 翻转窗口
			FlipWindow();

			FPSControl();
		}

		return true;
	}

	bool Window::OnceWindow()
	{
		if(GAF_pTHEAPP->IsQuit())
			return false;

		// 切换场景
		if(!SwitchScene())
			return false;

		// 更新窗口
		UpdateWindow();
		// 渲染窗口
		RenderWindow();
		// 空闲窗口
		IdleWindow();

		return true;
	}

	void Window::UpdateWindow()
	{
		if(m_pscnTop != SCENE_NULL)
		{
			UpdateScene(m_pscnTop);
		}

		// 应用程序更新
		GAF_pTHEAPP->UpdateApp();
	}

	void Window::RenderWindow()
	{
		if(m_pscnTop != SCENE_NULL)
		{
			// 更新顶层场景绘制对象
			m_pscnTop->ResetCanvas();
			// 渲染顶层场景
			RenderScene(m_pscnTop);
		}

		GAF_pTHEPLATFORM->RanderWindow(m_pWndHandle);
	}

	void Window::FlipWindow()
	{
		GAF_pTHEPLATFORM->FlipWindow(m_pWndHandle);
	}

 	void Window::IdleWindow()
 	{
		GAF_pTHEAPP->UpdateTimers();
		GAF_pTHEAPP->UpdateExactTimers();
	}

	void Window::ShowScene(Scene* pScene, bool isEnforce)
	{
		m_pscnShow = pScene;
		m_isShowEnforce = isEnforce;
	}

	void Window::CallScene(Scene* pScene)
	{
		m_pscnCall = pScene;
	}

	bool Window::SwitchScene()
	{
GOTO_WINDOW_SWITCHSCENE_STEP1:

		// 处理主场景自行退出
		if(m_pscnTop != m_pscnMain && m_pscnTop->IsAllowExit())
		{
			if(m_pscnTop != SCENE_NULL)
			{
				if(m_pscnTop->GetState() < SCENE_EXIT)
				{
					// 顶层场景退出
					switch(m_pscnTop->Exit())
					{
					case ID_YES:
						break;
					case ID_NO:
					case ID_WAIT:
					default:
						goto GOTO_WINDOW_SWITCHSCENE_STEP2;
					}
				}

				if(m_pscnTop->GetState() == SCENE_END)
				{
					// 结束并更换顶层场景
					if(m_pscnTop == m_pscnMain)
					{
						// 为主场景，则为退出程序
						if(m_pscnShow == SCENE_NULL)
							m_pscnShow = NULL;
						goto GOTO_WINDOW_SWITCHSCENE_STEP2;
// 						EndScene(m_pscnTop);
// 
// 						GAF_pTHEAPP->TurnOffScene(m_pscnMain);
// 						m_pscnMain = NULL;
// 						m_pscnTop = m_pscnMain;
// 
// 						return false;
					}
					else
					{
						// 为呼叫场景，则转为底层场景
						Scene* _pscnEnd = m_pscnTop;
						m_pscnTop = _pscnEnd->GetBackScene();
						EndScene(_pscnEnd);

						m_pscnTop->Resume();
						m_pscnTop->OnCallEnd(_pscnEnd);
						_pscnEnd = NULL;

						// 继续检查下层场景
						goto GOTO_WINDOW_SWITCHSCENE_STEP1;
					}
				}
			}
		}

GOTO_WINDOW_SWITCHSCENE_STEP2:

		// 更换主场景
		if(m_pscnShow != SCENE_NULL)
		{
			// 如果更换的主场景为当前主场景，忽略更换主场景操作。
			if(m_pscnShow == m_pscnMain)
			{
				m_pscnShow = SCENE_NULL;
				return true;
			}

			// 退出当前主场景
			if(m_pscnMain != SCENE_NULL)
			{
				// 退出主场景即调用场景
				if(m_pscnMain->GetState() == SCENE_RUN || m_pscnMain->GetState() == SCENE_PAUSE)
				{
					std::list<Scene*> _lstScenes;
					Scene* _pscnCur = m_pscnTop;
					while(_pscnCur != NULL)
					{
						_lstScenes.push_front(_pscnCur);
						_pscnCur = _pscnCur->GetBackScene();
					}

					ReturnID _rid = ID_WAIT;
					std::list<Scene*>::const_iterator _cit = _lstScenes.begin();
					while(true)
					{
						if(_cit == _lstScenes.end())
							break;

						_rid = (*_cit)->Exit(m_isShowEnforce);
						if(m_isShowEnforce)
							_rid = ID_YES;

						if(_rid == ID_YES)
						{
							// 继续向上层场景询问
							_cit++;
						}
						else if(_rid == ID_NO)
						{
							// 取消下层场景退出状态
							while(true)
							{
								if(_cit == _lstScenes.begin())
									break;

								_cit--;
								(*_cit)->CancelExit();
							}
							m_pscnShow = SCENE_NULL;
							goto GOTO_WINDOW_SWITCHSCENE_STEP3;
						}
						else if(_rid == ID_WAIT)
							goto GOTO_WINDOW_SWITCHSCENE_STEP3;
						else
							goto GOTO_WINDOW_SWITCHSCENE_STEP3;
					}

					// 退出上层场景
					if(m_pscnTop != m_pscnMain)
						goto GOTO_WINDOW_SWITCHSCENE_STEP1;
				}

				// 结束主场景
				if(m_pscnMain->GetState() == SCENE_END)
				{
					EndScene(m_pscnMain);
					GAF_pTHEAPP->TurnOffScene(m_pscnMain);
					m_pscnMain = SCENE_NULL;
					m_pscnTop = SCENE_NULL;
				}
			}

			// 更换并开始主场景
			if(m_pscnMain == SCENE_NULL)
			{
				// 更换主场景
				m_pscnMain = m_pscnShow;
				m_pscnShow = SCENE_NULL;
				m_isShowEnforce = false;

				// 结束程序
				if(m_pscnMain == NULL)
				{
					m_pscnTop = NULL;
					return false;
				}
				// 否则，开始主场景
				else if(m_pscnMain != SCENE_NULL)
				{
					if(m_pscnMain->GetState() == SCENE_FREE)
					{
						if(!StartScene(m_pscnMain))
						{
							GAF_pTHEAPP->TurnOffScene(m_pscnMain);
							m_pscnMain = SCENE_NULL;
							return false;
						}
						// 设为顶层场景
						m_pscnTop = m_pscnMain;
					}
				}
			}
		}

GOTO_WINDOW_SWITCHSCENE_STEP3:

		// 调用呼叫场景
		if(m_pscnCall != SCENE_NULL)
		{
			if(m_pscnTop != m_pscnCall)
			{
				if(StartScene(m_pscnCall))
				{
					m_pscnTop->Pause();
					m_pscnTop = m_pscnCall;
				}
			}
			m_pscnCall = SCENE_NULL;
		}

GOTO_WINDOW_SWITCHSCENE_END:

		return true;
	}

	bool Window::StartScene(Scene* pScene)
	{
		pScene->SetWindow(this);

		Scene* _pCurTop = (m_pscnTop == SCENE_NULL) ? NULL : m_pscnTop;

		if(!pScene->Start(_pCurTop))
		{
			pScene->SetWindow(NULL);
			return false;
		}

		GAF_pTHEPLATFORM->ClearCommandBuffer(m_pWndHandle);
		return true;
	}

	void Window::EndScene(Scene* pScene)
	{
		GAF_pTHEPLATFORM->ClearCommandBuffer(m_pWndHandle);

		pScene->End();
	}

	void Window::UpdateScene(Scene* pScene)
	{
		static Command s_cmdGet;

		// 顺序索取所有事件
		while(pScene->GetState() == SCENE_RUN && GetCommand(s_cmdGet))
		{
			if(GAF_COMMAND_ISWINDOW(s_cmdGet.nCmdID))
			{
				switch(s_cmdGet.nCmdID)
				{
				case COMMAND_QUIT:
					GAF_pTHEAPP->QuitApp(true);
					break;
				default:
					break;
				}
			}
			else if(GAF_COMMAND_ISOPERATION(s_cmdGet.nCmdID))
			{
				switch(s_cmdGet.nCmdID)
				{
				case COMMAND_KEY_DOWN:
					((CommandListener*)pScene)->KeyDown(s_cmdGet.lParam1);
					break;
				case COMMAND_KEY_UP:
					((CommandListener*)pScene)->KeyUp(s_cmdGet.lParam1);
					break;
				case COMMAND_CURSOR_DOWN:
					((CommandListener*)pScene)->CursorDown(s_cmdGet.lParam1, s_cmdGet.lParam2);
					break;
				case COMMAND_CURSOR_UP:
					((CommandListener*)pScene)->CursorUp(s_cmdGet.lParam1, s_cmdGet.lParam2);
					break;
				case COMMAND_CURSOR_MOVE:
					((CommandListener*)pScene)->CursorMove(s_cmdGet.lParam2);
					break;
				default:
					break;
				}
			}
		}

		// 更新
		if(pScene->GetState() == SCENE_RUN)
			pScene->Update();
	}

	void Window::RenderScene(Scene* pScene)
	{
		if(!pScene->IsFullWindow())
		{
			Scene* pBackScene = pScene->GetBackScene();

			if(pBackScene != NULL)
			{
				RenderScene(pBackScene);
			}
		}

		pScene->GetCanvas()->Render();
	}

	void Window::SetFPS(UINT nFPS)
	{
		m_nFPS = nFPS;

		if(m_nFPS == 0)
			m_ttFPST = 0;
		else
			m_ttFPST = 1000 / nFPS;
	}

	UINT Window::GetFPS()
	{
		return m_nFPS;
	}

	void Window::SetTitle(const STD_STRING strTitle)
	{
		GAF_pTHEPLATFORM->SetWindowTitle(m_pWndHandle, strTitle);
	}

	Scene* Window::GetTopScene()
	{
		if(m_pscnTop == SCENE_NULL)
			return NULL;
		return m_pscnTop;
	}

	bool Window::GetCommand(Command& cmdGet)
	{
		cmdGet.Reset();

		if(GAF_pTHEPLATFORM->GetCommand(m_pWndHandle, cmdGet))
		{
			if(GAF_COMMAND_ISWINDOW(cmdGet.nCmdID))
			{
				if(OnGetCommand(cmdGet))
				{
					cmdGet.nCmdID = COMMAND_NOTHING;
					return false;
				}
			}
			else if(GAF_COMMAND_ISOPERATION(cmdGet.nCmdID))
			{
				if(m_pscnTop->OnGetCommand(cmdGet))
				{
					cmdGet.nCmdID = COMMAND_NOTHING;
					return false;
				}
			}

			return true;
		}

		return false;
	}

	WindowHandle Window::GetHandle()
	{
		return m_pWndHandle;
	}

 	void Window::FPSControl()
 	{
//  		m_ttFPSUse = GAF_pTHEPLATFORM->GetTimeTicks() - m_ttSaveFPS;
//  		if(m_ttFPSUse < ATTRIB(FPSTime))
// 		{
// 			GAF_pTHEPLATFORM->Delay(ATTRIB(FPSTime) - m_ttFPSUse);
// 		}

// 		GAF_NOTE("Use Time = %d\n", GAF_pTHEPLATFORM->GetTimeTicks() - m_ttSaveFPS);

#ifdef GAF_FPS_CONTROL
		do
		{
#endif
			m_ttFPSTUse = GAF_pTHEPLATFORM->GetTimeTicks() - m_ttSaveFPST;
#ifdef GAF_FPS_CONTROL
		}while(m_ttFPSTUse < m_ttFPST);
#endif
// 		GAF_NOTE("Frame Ues Time = %d\n", m_ttFPSTUse);
		m_ttSaveFPST = GAF_pTHEPLATFORM->GetTimeTicks();
 	}
}
